﻿#include "Spi.h"
#include <iostream>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include "Timer.hpp"
extern pthread_cond_t doneCond; 
extern pthread_mutex_t doneMutex; 

using namespace std;

bool IsErrorRspInfo(CThostFtdcRspInfoField *pRspInfo)
{
    bool bResult = ((pRspInfo) && (pRspInfo->ErrorID != 0));
    if (bResult)
    {
        cerr << ">>> ErrorID=" << pRspInfo->ErrorID<<endl;// << ", ErrorMsg=" << pRspInfo->ErrorMsg << endl;
    }

    return bResult;
}


MdSpi::MdSpi()
{
	status=0;
}

void MdSpi::OnFrontConnected()
{
	status=1;
}

void MdSpi::OnFrontDisconnected(int nReason)
{
}

void MdSpi::OnRspUserLogin(CThostFtdcRspUserLoginField *pRspUserLogin, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
    if (!bIsLast || IsErrorRspInfo(pRspInfo))
		return;
	status=2;
}

void MdSpi::OnRspError(CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
    IsErrorRspInfo(pRspInfo);
}



void MdSpi::OnRtnDepthMarketData(CThostFtdcDepthMarketDataField *Rtn)
{

	Snapshot s;
	s.OpenInterest = Rtn->OpenInterest;
	s.Volume = Rtn->Volume;
	s.BidPrice1 = Rtn->BidVolume1>0?1000*(Rtn->BidPrice1):0;
	s.AskPrice1 = Rtn->AskVolume1>0?1000*(Rtn->AskPrice1):0;
	s.BidVolume1 = Rtn->BidVolume1;
	s.AskVolume1 = Rtn->AskVolume1;
	s.UpperLimitPrice = 1000*Rtn->UpperLimitPrice;
	s.LowerLimitPrice = 1000*Rtn->LowerLimitPrice;
	s.Time = Timer::time2int(Rtn->UpdateTime, Rtn->UpdateMillisec );
	s.nano = Timer::getNano();
	auto it = snapshot_.find(Rtn->InstrumentID);
	if(it == snapshot_.end())
		return;
	memcpy(it->second, &s, sizeof(Snapshot));
	it->second++;
}

TdSpi::TdSpi()
{
}

void TdSpi:: OnFrontDisconnected(int nReason)
{
    cerr << ">>> MdFrontDisconnected Reason = " << nReason << endl;
}

void TdSpi::OnHeartBeatWarning(int nTimeLapse)
{
    cerr << ">>> TradeHeartBeatWarning nTimerLapse = " << nTimeLapse << endl;
}

void TdSpi::OnFrontConnected()
{
    pthread_mutex_lock(&doneMutex);     
    pthread_cond_signal(&doneCond); 
    pthread_mutex_unlock (&doneMutex); 
}

void TdSpi::OnRspAuthenticate(CThostFtdcRspAuthenticateField *pRspAuthenticateField,CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
	if (bIsLast && !IsErrorRspInfo(pRspInfo))
    {
        pthread_mutex_lock(&doneMutex);
        pthread_cond_signal(&doneCond);
        pthread_mutex_unlock (&doneMutex);
    }

}

void TdSpi::OnRspUserLogin(CThostFtdcRspUserLoginField *pRspUserLogin,
                               CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
    if (bIsLast && !IsErrorRspInfo(pRspInfo))
    {
        pthread_mutex_lock(&doneMutex); 
        pthread_cond_signal(&doneCond); 
        pthread_mutex_unlock (&doneMutex); 
    }
}


void TdSpi::OnRspSettlementInfoConfirm(CThostFtdcSettlementInfoConfirmField *pSettlementInfoConfirm, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
    pthread_mutex_lock(&doneMutex); 
    pthread_cond_signal(&doneCond); 
    pthread_mutex_unlock (&doneMutex); 
}

void TdSpi::OnRspQryInstrument(CThostFtdcInstrumentField *Rtn, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
	if(Rtn->ExpireDate[0]!=0 &&
		strcmp(Rtn->ExpireDate,"20370101") < 0 &&
		Rtn->IsTrading &&
		Rtn->OptionsType==0)
	{
		string id = Rtn->InstrumentID;
		string t;
		for(const char& c:id)
		{
			if(c>='0' && c<='9')
				break;
			t+=c;
		}
		if(universe_.find(t) == universe_.end())
			return;
		list_.push_back(id);
		//fprintf(stdout,"%s %s\n",t.c_str(),id.c_str());
	}
	if (bIsLast && !IsErrorRspInfo(pRspInfo))
    {
        pthread_mutex_lock(&doneMutex);
        pthread_cond_signal(&doneCond);
        pthread_mutex_unlock (&doneMutex);
    }

}


void TdSpi::OnRspError(CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
    IsErrorRspInfo(pRspInfo);
}

void TdSpi::OnRtnInstrumentStatus(CThostFtdcInstrumentStatusField *Rtn)
{
	auto it = universe_.find(Rtn->InstrumentID);
	if(it == universe_.end())
		return;
	if( Timer::isClose(Timer::time2int(Rtn->EnterTime, 0)) )
	{
		closed_ = true;
	}
}


